#include "../utils/pch.h"
#include "../utils/IniReader.h"
#include "../utils/PcapUtils.h"
#include "main.h"
#include "../utils/SafeQueueTemplate.h"
#include "../utils/SPMCQueueTemplate.h"


// 全局共享配置
namespace Global {
    const std::string Version = "0.0.2";
    const std::string Date = "0.0.2";
}

namespace ntp{
    // 定义全局变量
    std::string global_message = "Hello, World!";
    std::mutex global_mutex;

    // 共享的日志对象
    std::shared_ptr<spdlog::logger> my_nm_logger;



    // 共享队列1 = 普通队列
    std::queue<MarketData> data_queue1;
    std::queue<MarketData> data_queue2;
    SafeQueue<MarketData> queueLine1, queueLine2;
    constexpr uint32_t QUEUE_SIZE = 16; // 队列大小必须是2的幂次
    SPMCQueue<MarketData, 1024> queueL1, queueL2;



}

#define HOME_DIR "/tmp/tmp.FdUHWCPhyb/V2"

std::shared_ptr<spdlog::logger> spdlog_init() {
    // 初始化异步线程池
    spdlog::init_thread_pool(8192, 1);
    // 创建 sinks
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    console_sink->set_level(spdlog::level::debug);

    auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(
            "logs/app.log", 1024 * 1024 * 5, 3);
    file_sink->set_level(spdlog::level::info);

    // 创建异步日志器
    auto logger = std::make_shared<spdlog::async_logger>(
            "async_logger", spdlog::sinks_init_list{console_sink, file_sink},
            spdlog::thread_pool(), spdlog::async_overflow_policy::block);
    logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%l] [%s:%#] %v");
    spdlog::register_logger(logger);

    return logger;
}

int main() {
    using namespace ntp;

    // 初始化运行时日志
    //ntp::my_nm_logger = spdlog::basic_logger_mt("test_logger", "runingTimeLogger.txt"); // basic_logger 固定写法
    //spdlog::set_default_logger(my_nm_logger);
    //spdlog::flush_on(spdlog::level::info);
    //spdlog::get("test_logger")->info("LoggingTest::ctor");

    ntp::my_nm_logger = spdlog_init();
    // 使用日志器
    SPDLOG_LOGGER_DEBUG(my_nm_logger, "日志测试1 Debug message (only console)");
    SPDLOG_LOGGER_INFO(my_nm_logger, "日志测试2 (both console and file)");
    SPDLOG_LOGGER_ERROR(my_nm_logger, "日志测试3 - error");

    SPDLOG_LOGGER_INFO(my_nm_logger,"============================ 程序开始执行 ============================");
    SPDLOG_LOGGER_INFO(my_nm_logger,"version: {},spdlog: {}", Global::Version, my_nm_logger->name());


    // 获取启动时间
    auto aa = currTime();
    // 获取当前时间作为启动时间
    std::chrono::system_clock::time_point startTime = std::chrono::system_clock::now();
    // 获取当前工作路径
    char cwd[1024];
    if (getcwd(cwd, sizeof(cwd)) == NULL) {
        perror("getcwd");
        return 1;
    }


    // 初始化配置文件对象
    IniReader* iniCfg = new IniReader();
    std::string cwdStr(cwd);
    std::string cfgPathName = cwdStr + "/my_config.ini";
    //std::string cfgPathName = HOME_DIR"/my_config.ini";

    SPDLOG_LOGGER_INFO(my_nm_logger, "程序启动路径为：{} ,启动时间：{}", cwd, aa);
    SPDLOG_LOGGER_INFO(my_nm_logger, "读取的配置文件：{}", cfgPathName);

    if (!iniCfg->ReadConfig(cfgPathName)) {
        SPDLOG_LOGGER_INFO(my_nm_logger, "读取 ini 配置文件失败");
        exit;
    }
    else {
        SPDLOG_LOGGER_INFO(my_nm_logger, "读取 my_config.ini 配置文件成功");
    }

    // 初始化公共数据类
    ShareDataClzz* shareDataClzz = new ShareDataClzz(iniCfg);


    // pcap库测试
    PcapUtils pcapUtils(my_nm_logger, shareDataClzz);
    //PcapUtils pcapUtils;
    //pcapUtils.readPcapFile();
    //pcapUtils.readNetworkInterface();
    //pcapUtils.readNetworkIface();
    //pcapUtils.readNetworkIface4();


    // 读取两路行情，用同一个起点做对比
    auto readLambda = [](PcapUtils pcapUtils, std::shared_ptr<spdlog::logger> my_logger,
            IniReader* iniCfg, std::chrono::system_clock::time_point startTime, SafeQueue<MarketData>* data_queue1, SafeQueue<MarketData>* data_queue2) {
        SPDLOG_LOGGER_INFO(my_logger,"消费者线程 - 启动读行情线程");
        pcapUtils.readMsg(my_logger, iniCfg, data_queue1, data_queue2);
    };
    //std::thread task2(readLambda, pcapUtils, my_nm_logger, iniCfg, startTime, data_queue1);
    //std::thread task2(readLambda, pcapUtils, my_nm_logger, iniCfg, startTime, &queueLine1, &queueLine2);

    // 写行情1
    auto writeLambda1 = [](ntp::PcapUtils pcapUtils, std::shared_ptr<spdlog::logger> my_logger,
            IniReader* iniCfg, std::chrono::system_clock::time_point startTime, SafeQueue<MarketData>* data_queue) {
        SPDLOG_LOGGER_INFO(my_logger,"生产者线程1 - 启动写行情线程1");
        pcapUtils.readNetworkIfaceLine("LINE_1", startTime, iniCfg, data_queue);
    };
    //std::thread task(writeLambda, pcapUtils, my_nm_logger, iniCfg, startTime, data_queue1);
    //std::thread task(writeLambda1, pcapUtils, my_nm_logger, iniCfg, startTime, &queueLine1);

    // 写行情2
    auto writeLambda2 = [](PcapUtils pcapUtils, std::shared_ptr<spdlog::logger> my_logger,
            IniReader* iniCfg, std::chrono::system_clock::time_point startTime, SafeQueue<MarketData>* data_queue) {
        SPDLOG_LOGGER_INFO(my_logger,"生产者线程2 - 启动写行情线程2");
        pcapUtils.readNetworkIfaceLine("LINE_2", startTime, iniCfg, data_queue);
    };
    //std::thread task3(writeLambda2, pcapUtils, my_nm_logger, iniCfg, startTime, &queueLine2);

    // 采样统计
    auto sampledLambda = [](PcapUtils pcapUtils, std::shared_ptr<spdlog::logger> my_logger, IniReader* iniCfg, std::chrono::system_clock::time_point startTime) {
        my_logger->info("采样统计线程 - 启动读行情线程");
        pcapUtils.sampled(my_logger, iniCfg);
    };
    //std::thread task4(sampledLambda, pcapUtils, my_nm_logger, iniCfg, startTime);

    // 等待线程结束
    //task2.join();
    //task.join();
    //task3.join();
    //task4.join();


    // 多路行情数据采集


    // 循环创建多个线程，采集，写文件
    auto threadWork = [](ntp::PcapUtils pcapUtils, std::shared_ptr<spdlog::logger> my_logger,
                           IniReader* iniCfg, std::chrono::system_clock::time_point startTime) {
        SPDLOG_LOGGER_INFO(my_logger,"生产者线程1 - 启动写行情线程1");
        pcapUtils.readNetwork("LINE_1", startTime, iniCfg);
    };
    std::vector<std::thread> threads;
    for (int i = 0; i < 4; i++) {
        std::thread task4(threadWork, pcapUtils, my_nm_logger, iniCfg, startTime);
        threads.push_back(std::move(task4));
    }
    // 线程数量
    std::cout << "线程数量: " << threads.size() << std::endl;
    for (auto& thread : threads) {
        thread.join();
    }


    // ps -T -p $(pgrep Network_Traffic_Processing_V2)

}
